﻿using System;
using System.Collections.Generic;
using System.Threading;
using System.Linq;
using System.Linq.Expressions;
using System.Xml.Linq;
using System.Diagnostics;
using System.IO;
using System.Xml;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Globalization;

using Styx;
using Styx.Logic.Combat;
using Styx.Database;
using Styx.Helpers;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;
using Styx.Plugins.PluginClass;
using Styx.Logic.BehaviorTree;

using Styx.Logic.Pathing;
using Styx.Combat.CombatRoutine;
using Styx.Logic.Inventory.Frames.Quest;
using Styx.Logic.Questing;
using Styx.Plugins;
using Styx.Logic.Inventory.Frames.Gossip;
using Styx.Logic.Common;
using Styx.Logic.Inventory.Frames.Merchant;
using Styx.Logic;
using Styx.Logic.Profiles;
using Styx.Logic.Inventory.Frames.LootFrame;
using Styx.Logic.BehaviorTree;
using Styx.Logic.POI;
using Styx.Logic.Questing;
using TreeSharp;
using Action = TreeSharp.Action;

namespace ProfileChangerII
{	
    class ProfileChangerII : HBPlugin
    {
        	public override string Name { get { return "Profile Changer II"; } }
       	public override string Author { get { return "katzerle & DaLord"; } }
       	private readonly Version _version = new Version(1, 3 );
        	public override Version Version { get { return _version; } }
       	public override string ButtonText { get { return "Settings"; } }
       	public override bool WantButton { get { return true; } }

       	public static ProfileChangerSettings Settings = new ProfileChangerSettings();
       	public static LocalPlayer Me = ObjectManager.Me;
        	bool hasItBeenInitialized = false;
	 	private float X, Y, Z;

       	 public static Int32 ContinentID;
        	public static WoWPoint PortalLocation = new WoWPoint(0, 0, 0);
        	public static Int32 PortalID;
        		
        	public static Stopwatch SWProfile = new Stopwatch();
        		
		public static bool Hearted = false;
		public static bool NoHeart = false;
		public static bool NoPortal = false;
		public static bool PortalUsed = false;
		public static int Curent = 0;
		public static bool UseMin = false;
		public static bool UseLvl = false;
		
		public static bool Active = false;        	  
		public static string Profile;
		public static int Minutes;
		public static string Portal;
		public static bool Heart = false;
				
		
        public ProfileChangerII()
           { 	
        	PluginUpdate();
    		Logging.Write(System.Drawing.Color.LightSkyBlue, "Profile Changer II - Version {0} - BETA",Version);
       	}

		public override void OnButtonPress()
        {ConfigForm.ShowDialog();}

        private Form MyForm;
        public Form ConfigForm
        {
            get
            {
                if (MyForm == null)
                    MyForm = new ProfileChangerUI();
                return MyForm;
            }
        }
  
	public override void Pulse()
		{ 			  
    		//CharacterSettings.Instance.BotName = ;

			if (!hasItBeenInitialized)
                {
				Myread();
                   Logging.Write(System.Drawing.Color.LightSkyBlue, "Profile Changer: Starting");
					 SWProfile.Reset();
					 SWProfile.Start();
					 Logging.Write(System.Drawing.Color.LightSkyBlue, "Profile Changer: Initial Timer Started");
					ChangeProfile(Profile);
					hasItBeenInitialized = true;					
                }

                if (Active)
                {
                	if (UseMin)
                	{
                		if (SWProfile.Elapsed.TotalMinutes > Minutes && HijackThread())
                		{
                		DoThis();
                		}                 	
                	}
                
                	if (UseLvl)
                	{
                		if (Me.Level > Minutes && HijackThread())
                		{
                		DoThis();	
                		}                 	
                	}
                	
                }
                else
				{
				Curent = 0;	
				Myread();	
				}
		}
		
                
	public static void DoThis()
	        {
                if (Heart && !Hearted)
					  {
					   	HeartMe();
					  }
					if ((Portal != "") && (Portal != "no Portal") && !PortalUsed )
					{
						if (!NoHeart)
						{
				 		Thread.Sleep(1000);
				 		Logging.Write(System.Drawing.Color.LightSkyBlue, "Profile Changer: Portal");
	             		UsePortal(Portal);
						}
	            	}
					if (!NoHeart && !NoPortal)
						{
						Myread();
						NotInGame();
						}
						Thread.Sleep(100);
					if (Active)
                   		{
					 	Logging.Write(System.Drawing.Color.LightSkyBlue, "Profile Changer: Change Profile and Reset Timer");
					 	SWProfile.Reset();
					 	Thread.Sleep(100);
					 	SWProfile.Start();
					 	Logging.Write(System.Drawing.Color.LightSkyBlue, "Profile Changer: Timer Reset and new Timer Started");
					 	ChangeProfile(Profile);
					 	Thread.Sleep(1000);
						}
                   	else
                     {
                        if (UseLvl)
                		{
                        Dismount();
                    	Logging.Write(System.Drawing.Color.LightSkyBlue, "Profile Changer: Log Out Now, bb");
                    	Lua.DoString("ForceQuit()");
                    	return; 
                        }
                        else
                        {
                   		if (Settings.StopBot )
                       	   {
                        	Dismount();
                        	Logging.Write(System.Drawing.Color.LightSkyBlue, "Profile Changer: Log Out Now, bb");
                        	Lua.DoString("ForceQuit()");
                        	return;
                        	}
                        	else
                        	{
							Curent = 0;
							Myread();
							NotInGame();
							Logging.Write(System.Drawing.Color.LightSkyBlue, "Profile Changer: Change Profile and Reset Timer");
					 		SWProfile.Reset();
					 		SWProfile.Start();
					 		Logging.Write(System.Drawing.Color.LightSkyBlue, "Profile Changer: Timer Reset and new Timer Started");
					 		ChangeProfile(Profile);
                        	}
                   		}
						Hearted = false;
						PortalUsed = false;
						NoHeart = false;
						NoPortal = false;
						
					}
                 return;  	
           }
           
	public static void HeartMe()
	        {	         	
	        Logging.Write(System.Drawing.Color.LightSkyBlue, "Profile Changer: Using Heartstone");	        	        
	         ObjectManager.Update();
	            List<WoWItem> HearthItems = ObjectManager.GetObjectsOfType<WoWItem>()
	             .Where(o => ((o.Entry == 6948) || (o.Entry == 64488)))
	             .OrderBy(o => o.Distance).ToList();	        

	            if(HearthItems == null || HearthItems.Count() == 0)
	            { 	            
	           		 if (SpellManager.HasSpell("Astral Recall") && SpellManager.CanCast("Astral Recall"))
	   				{
	   				 SpellManager.Cast("Astral Recall");	
	    			}	            	
	   				 else	
	   				{
	                	Logging.Write(System.Drawing.Color.Red, "Profile Changer: No hearthstone available so aborting hearth.");
				        if (Settings.StopBot)
                   	 	{
				        Logging.Write(System.Drawing.Color.Red, "Profile Changer: Set to Quit after last profile so quiting");	
                    	Dismount();
                    	Logging.Write(System.Drawing.Color.LightSkyBlue, "Profile Changer:Quitting WoW...");
                    	Lua.DoString("ForceQuit()");
                    	return;
                    	}
						else
						{
	                	NoHeart = true;	                
	                	return;
						}
	            	}
	            }      
           		WoWItem Hearth = HearthItems.FirstOrDefault();
            	if(Hearth.Cooldown == 0)
            	{
                Logging.Write(System.Drawing.Color.Red, "Profile Changer: hearthstone in progress.");
                Thread.Sleep(5000);
                WoWMovement.MoveStop();	
                Hearth.Use();
                NoHeart = false;
                Hearted = true;
                Thread.Sleep(1000);
                NotInGame();
                Logging.Write(System.Drawing.Color.LightSkyBlue, "Profile Changer: hearthstone Done!");
			 	}
            	else
            	{
            	NoHeart = true;
            	Hearted = true;
                Logging.Write(System.Drawing.Color.Red, "Profile Changer: Hearthstone not yet cooled down");
            	}            		
	            return;
		}
	         
	public static void ChangeProfile(string Profile)
		    {
		    Logging.Write(System.Drawing.Color.LightSkyBlue, "Profile Changer: Load Profile: {0}", Profile);
			Thread.Sleep(200);
		    ProfileManager.LoadNew(Profile);
		    Thread.Sleep(2000); 
		    Logging.Write(System.Drawing.Color.LightSkyBlue, "Profile Changer: Task Done!");
			return;
		    }

	public static void UsePortal(string Portal)// Redo w/ XML read
        {

            if (Portal == "SW --> Hyjal")
            {
                ContinentID = 0;
                PortalLocation = new WoWPoint(-8208.911, 429.271, 118.0898);
                PortalID = 207692;
				InteractWithPortal(ContinentID, PortalLocation, PortalID, Portal);
            }
            else if (Portal == "SW --> Uldum")
            {
                ContinentID = 0;
                PortalLocation = new WoWPoint(-8208.911, 429.271, 118.0898);
                PortalID = 207695;
				InteractWithPortal(ContinentID, PortalLocation, PortalID, Portal);
            }
            else if (Portal == "SW --> Twilight Highland")
            {
                ContinentID = 0;
                PortalLocation = new WoWPoint(-8208.911, 429.271, 118.0898);
                PortalID = 207694;
				InteractWithPortal(ContinentID, PortalLocation, PortalID, Portal);
            }
            else if (Portal == "SW --> Deepholm")
            {
                ContinentID = 0;
                PortalLocation = new WoWPoint(-8208.911, 429.271, 118.0898);
                PortalID = 207693;
				InteractWithPortal(ContinentID, PortalLocation, PortalID, Portal);
            }
            else if (Portal == "SW --> Tol Barad")
            {
                ContinentID = 0;
                PortalLocation = new WoWPoint(-8208.911, 429.271, 118.0898);
                PortalID = 206594;
				InteractWithPortal(ContinentID, PortalLocation, PortalID, Portal);
            }

            //xxx to Stormwind	
            else if (Portal == "Twilight Highland --> SW")
            {
                ContinentID = 0;
                PortalLocation = new WoWPoint(-4886.898, -6633.685, 9.818425);
                PortalID = 205248;
				InteractWithPortal(ContinentID, PortalLocation, PortalID, Portal);
            }
			
            //Twilight Highland to Uldum combo portal	
            else if (Portal == "Twilight --> Uldum(Combo)")
            {
            	Logging.Write(System.Drawing.Color.LightSkyBlue, "Profile Changer: 1st part Twilight to SW");
                ContinentID = 0;
                PortalLocation = new WoWPoint(-4886.898, -6633.685, 9.818425);
                PortalID = 205248;
				InteractWithPortal(ContinentID, PortalLocation, PortalID, Portal);
				
				Logging.Write(System.Drawing.Color.LightSkyBlue, "Profile Changer: 2nd part SW to Uldum");
				ContinentID = 0;
                PortalLocation = new WoWPoint(-8208.911, 429.271, 118.0898);
                PortalID = 207695;
				InteractWithPortal(ContinentID, PortalLocation, PortalID, Portal);
			}
            
           else if (Portal == "Deepholm --> SW")
            {
                ContinentID = 646;
                PortalLocation = new WoWPoint(991.2067, 550.2415, -49.33485);
                PortalID = 205272;
				InteractWithPortal(ContinentID, PortalLocation, PortalID, Portal);
            }
            else if (Portal == "Tol Barad --> SW")
            {
                ContinentID = 732;
                PortalLocation = new WoWPoint(-348.4281, 1043.762, 21.60393);
                PortalID = 208227;
				InteractWithPortal(ContinentID, PortalLocation, PortalID, Portal);
            }
			
			//Orgrimmar to xxx
            else if (Portal == "OG --> Hyjal")
            {
                ContinentID = 1;
                PortalLocation = new WoWPoint(2049.351, -4376.577, 98.84486);
                PortalID = 207688;
				InteractWithPortal(ContinentID, PortalLocation, PortalID, Portal);
            }
            else if (Portal == "OG --> Uldum")
            {
                ContinentID = 1;
                PortalLocation = new WoWPoint(2049.351, -4376.577, 98.84486);
                PortalID = 207687;
				InteractWithPortal(ContinentID, PortalLocation, PortalID, Portal);
            }
            else if (Portal == "OG --> Twilight Highland")
            {
                ContinentID = 1;
                PortalLocation = new WoWPoint(2049.351, -4376.577, 98.84486);
                PortalID = 207686;
				InteractWithPortal(ContinentID, PortalLocation, PortalID, Portal);
            }
            else if (Portal == "OG --> Deepholm")
            {
                ContinentID = 1;
                PortalLocation = new WoWPoint(2049.351, -4376.577, 98.84486);
                PortalID = 207689;
				InteractWithPortal(ContinentID, PortalLocation, PortalID, Portal);
            }
            else if (Portal == "OG --> Tol Barad")
            {
                ContinentID = 1;
                PortalLocation = new WoWPoint(2049.351, -4376.577, 98.84486);
                PortalID = 206595;
				InteractWithPortal(ContinentID, PortalLocation, PortalID, Portal);            }
			
			else if (Portal == "Deepholm --> OG")
            {
                ContinentID = 646;
                PortalLocation = new WoWPoint(1004.36, 504.324, -49.33377);
                PortalID = 205273;
				InteractWithPortal(ContinentID, PortalLocation, PortalID, Portal);
            }
            else if (Portal == "Tol Barad --> OG")
            {
                ContinentID = 732;
                PortalLocation = new WoWPoint(-607.5608, 1380.215, 22.00986);
                PortalID = 208226;
				InteractWithPortal(ContinentID, PortalLocation, PortalID, Portal);
            }
			else if (Portal == "Twilight Highland --> OG")
            {
                ContinentID = 0;
                PortalLocation = new WoWPoint(-4030.354, -6362.913, 39.51112);
                PortalID = 204917;
				InteractWithPortal(ContinentID, PortalLocation, PortalID, Portal);
            }
            else
			{
				Logging.Write(System.Drawing.Color.Red, "Can't find the Portal ({0}) you wanted to use", Portal);               
			}
			return;
        }

	public static void InteractWithPortal(int MyContinentID,WoWPoint MyPortalLocation,int MyPortalID,string MyPortal)
		{
			WoWPoint PortalHelperDeepholm2 = new WoWPoint(816.7787, 496.0443, -68.7848);
				Logging.Write(System.Drawing.Color.LightSkyBlue, "Profile Changer: Flying to {0}, Continent {1} to use Portal Id {2} for {3}", MyPortalLocation.ToString(), MyContinentID, MyPortalID, MyPortal);

				// Check if the Portal is on your Continent
				if (Me.MapId != MyContinentID)
				{
					Logging.Write(System.Drawing.Color.Red, "Can't reach Portal, it is on another Continent");
					NoPortal = true;
					return;
				}

				// Fly to the Portal
				if ((MyPortal == "SW --> Deepholm") || (MyPortal == "OG --> Deepholm"))
				{
					Logging.Write(System.Drawing.Color.LightSkyBlue, "Profile Changer: Move to Helperpoint Deepholm");
					while (PortalHelperDeepholm2.Distance(Me.Location) > 10)
					{
					Flightor.MoveTo(PortalHelperDeepholm2);
					Thread.Sleep(1000);
					}
				}
					Logging.Write(System.Drawing.Color.LightSkyBlue, "Profile Changer: Move to Portal");
					Logging.Write(System.Drawing.Color.LightSkyBlue, "Profile Changer: Using portal for {0}",MyPortal);
					while (MyPortalLocation.Distance(Me.Location) > 2)
					{
					Flightor.MoveTo(MyPortalLocation);
					Thread.Sleep(1000);
					}
				
				Dismount();
				ObjectManager.Update();
				List<WoWGameObject> objList2 = ObjectManager.GetObjectsOfType<WoWGameObject>()
					.Where(o => (o.Entry == MyPortalID))
					.OrderByDescending(o => o.Entry).ToList();

				// Interact with Portal
				foreach (WoWGameObject o in objList2)
				{
					Logging.Write(System.Drawing.Color.LightSkyBlue, "Profile Changer: Found Portal and moveing to it");

					while (o.Location.Distance(Me.Location) > 2)
					{
						Navigator.MoveTo(o.Location);
						Thread.Sleep(500);
					}
					
					Navigator.PlayerMover.MoveStop();
					Thread.Sleep(2000);
					if((o.Entry != 205248) && (o.Entry != 204917))
					{
						Thread.Sleep(1000);
						o.Interact();
						Thread.Sleep(2000);
					}
					
				}

				// Wait while not in Game 
					NotInGame();					
					NoPortal = false;
					//PortalUsed = true;
					Logging.Write(System.Drawing.Color.LightSkyBlue, "Profile Changer: Interact with Portal Done");
				return;	
		}
		
	public static void NotInGame()
		{
		while (ObjectManager.Me == null)	
			{
			Thread.Sleep(5000);
			}
			while (ObjectManager.Me.Location.X.ToString() == "0" && ObjectManager.Me.Location.Y.ToString() == "0" && ObjectManager.Me.Location.Z.ToString() == "0")
			{				
			Thread.Sleep(5000);				
			}				
			Thread.Sleep(18000);
			return;
	   }
		
	public static void Dismount()
        {
            if (StyxWoW.Me.IsFlying)
            {
                Logging.Write(System.Drawing.Color.LightSkyBlue, "Profile Changer:  Descending before dismount");
                Navigator.PlayerMover.Move(WoWMovement.MovementDirection.Descend);
                while (StyxWoW.Me.IsFlying)
                    { Thread.Sleep(250); }

                Navigator.PlayerMover.MoveStop();
            }

            if (StyxWoW.Me.Auras.ContainsKey("Flight Form"))
            {
                Logging.Write(System.Drawing.Color.LightSkyBlue, "Profile Changer: Cancelling Flight Form");
                CancelAura("Flight Form");
            }

            else if (StyxWoW.Me.Auras.ContainsKey("Swift Flight Form"))
            {
                Logging.Write(System.Drawing.Color.LightSkyBlue, "Profile Changer: Cancelling Swift Flight Form");
                CancelAura("Swift Flight Form");
            }

            else
            {
                Logging.Write(System.Drawing.Color.LightSkyBlue, "Profile Changer: Dismounting");
                Mount.Dismount();
            }
           return; 
        }
		
	public static void CancelAura(string sAura)
        {
            Lua.DoString(string.Format("RunMacroText(\"/cancelaura {0}\")", sAura), 0);
            return;
        }


	public static bool HijackThread()
        {
            if (Me.Combat || Me.Dead || Me.IsGhost || Me.IsInInstance || Me.Mounted || Me.IsFlying || Me.IsFalling || Me.IsCasting ||BotPoi.Current.Type == PoiType.Corpse || BotPoi.Current.Type == PoiType.Harvest || BotPoi.Current.Type == PoiType.Loot) return false;
			return true;
        }
		
	public static void Myread()
	   {						
            XmlDocument xml = new XmlDocument();
            XmlNode xvar;
           	string File = "Plugins\\ProfileChangerII\\config\\";
            string sPath = Process.GetCurrentProcess().MainModule.FileName;
            sPath = Path.GetDirectoryName(sPath);
            sPath = Path.Combine(sPath, File);
            sPath = Path.Combine(sPath, "ProfileChangerII.config");
            System.IO.FileStream fs = new System.IO.FileStream(@sPath, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.ReadWrite);
            xml.Load(fs);
            fs.Close();
            xvar = xml.SelectSingleNode("//ProfileChangerII/UseMinutes");
            if (xvar != null)
            {UseMin = Convert.ToBoolean(xvar.InnerText);}
            xvar = xml.SelectSingleNode("//ProfileChangerII/UseLevel");
            if (xvar != null)
            {UseLvl = Convert.ToBoolean(xvar.InnerText);}
            ++Curent; 
            xvar = xml.SelectSingleNode("//ProfileChangerII/Active"+Convert.ToString(Curent));
            Active = Convert.ToBoolean(xvar.InnerText);
        	xvar = xml.SelectSingleNode("//ProfileChangerII/Profile"+Convert.ToString(Curent));
            Profile = Convert.ToString(xvar.InnerText);
			xvar = xml.SelectSingleNode("//ProfileChangerII/Minutes"+Convert.ToString(Curent));
            Minutes = Convert.ToInt32(xvar.InnerText);
           	xvar = xml.SelectSingleNode("//ProfileChangerII/Heart"+Convert.ToString(Curent));
            Heart = Convert.ToBoolean(xvar.InnerText);
           	xvar = xml.SelectSingleNode("//ProfileChangerII/Portal"+Convert.ToString(Curent));
        	Portal = Convert.ToString(xvar.InnerText); 
			return;        	
       } 
	 static public void PluginUpdate()
		{
			string File = "Plugins\\ProfileChangerII";
			string sPath = Process.GetCurrentProcess().MainModule.FileName;
			sPath = Path.GetDirectoryName(sPath);
			sPath = Path.Combine(sPath, File);
			string Website = "https://profilechangerii.googlecode.com/svn/trunk";
			
			try
			{	
				WebClient client = new WebClient();
				IFormatProvider culture = new CultureInfo("fr-FR", true);
			
				XDocument VersionLatest = XDocument.Load(Website + "/config/Updater.xml");
				XDocument VersionCurrent = XDocument.Load(sPath + "\\config\\Updater.xml");

				string LatestVersionNumber = VersionLatest.Element("Updater").Element("Version").Value;
				string CurrenttVersionNumber = VersionCurrent.Element("Updater").Element("Version").Value;

				if (Convert.ToDecimal(CurrenttVersionNumber) < Convert.ToDecimal( LatestVersionNumber))
				{
				foreach (XElement fileNode in VersionLatest.Element("Updater").Descendants("File"))
				{ 
					
					string filename1 = Convert.ToString(fileNode.Element("Path").Value);
					bool download = Convert.ToBoolean(fileNode.Element("Download").Value);
					if (download)
					{
						string filename2 = filename1.Replace('/','\\');
						client.DownloadFile(Website + filename1, sPath + filename2);
					}
				}
			

				client.DownloadFile(Website + "/config/Updater.xml", sPath + "\\config\\Updater.xml");
				
				Logging.Write(System.Drawing.Color.LightSkyBlue, "Profile Changer: Downloaded new Version {0}", LatestVersionNumber);
				MessageBox.Show("Profile Changer: Downloaded new Version. Recompile Plugins or restart HB to use it !!!");
				}
			}
			catch (System.Threading.ThreadAbortException) { throw; }
			catch (Exception e)
			{
				Logging.WriteDebug(System.Drawing.Color.Red, "Profile Changer: Exception in Pulse: {0}", e);
			}
				return;  
		}	
  }
   
}
				
